package org.iabako.server.serviceimpl.business;

import org.iabako.server.dao.JpaDAO;
import org.iabako.server.dao.business.TrackingDAO;
import org.iabako.server.dao.user.UserDAO;
import org.iabako.server.tools.ServerTools;
import org.iabako.shared.entity.business.*;
import org.iabako.shared.entity.enumeration.TrackingType;
import org.iabako.shared.iservice.business.TrackingService;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * Created by jose on 04/05/15.
 */

@org.springframework.stereotype.Service("trackingService")
public class TrackingServiceImpl extends AbstractServiceImpl implements TrackingService {

    @Autowired
    TrackingDAO trackingDAO;
    @Autowired
    UserDAO userDAO;

    @Override
    protected JpaDAO getDAO() {
        return trackingDAO;
    }

    public List<TrackingObject> getTrackingObjects(Tracking tracking) {
        return trackingDAO.getTrackingObject(tracking);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addTrackingToUserSession(TrackingType trackingType, BusinessEntity trackingObject) {
        addTrackingToUserSession(trackingType, trackingObject, 1, null);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addTrackingToUserSession(TrackingType trackingType, BusinessEntity trackingObject, int cardinalNumber, String comment) {

        Tracking tracking = trackingDAO.getByTrackingTypeAndSessionUser(trackingType);
        if (tracking == null) {
            tracking = new Tracking();
            tracking.setType(trackingType);
            tracking.setUser(getSessionUser());
        }

        TrackingObject object = new TrackingObject();
        if (!isDeleteTrack(trackingType)) {
            if (trackingObject instanceof Client) {
                object.setClient((Client) trackingObject);
            } else if (trackingObject instanceof Product) {
                object.setProduct((Product) trackingObject);
            } else if (trackingObject instanceof Service) {
                object.setService((Service) trackingObject);
            } else if (trackingObject instanceof Sale) {
                object.setSale((Sale) trackingObject);
            } else if (trackingObject instanceof Expense) {
                object.setExpense((Expense) trackingObject);
            }
        }

        String deleteComment = getCommentIfBusinessObjectDeleted(trackingType, trackingObject);
        comment = deleteComment != null ? deleteComment : comment;
        comment = comment != null ? comment + "\n" : null;

        tracking.setCardinal(tracking.getCardinal() + cardinalNumber);
        tracking.setDate(new Date());
        if (comment != null) {
            tracking.setComment(tracking.getComment() != null ? tracking.getComment() + comment : comment);
        }

        tracking = trackingDAO.merge(tracking);

        if (object.hasTrackingObject()) {
            object.setTracking(tracking);
            //Cascading persist is disable because it makes doubles entries (with no reason!)
            trackingDAO.persistTrackingObject(object);
        }
    }

    public List<Tracking> getTodayTracking() {
        List<Tracking> trackingList = trackingDAO.getTodayTracking();

        for (Tracking tracking : trackingList) {
            if (tracking.getUser().equals(getSessionUser())) {
                tracking.setTransientUser(getSessionUser());
            } else {
                tracking.setTransientUser(userDAO.findById(tracking.getUser().getId()));
            }
        }
        return trackingList;
    }

    private String getCommentIfBusinessObjectDeleted(TrackingType trackingType, BusinessEntity trackingObject) {
        if (trackingType == TrackingType.clientDelete) {
            return "- " + messages.getLabel("tracking_client_delete_comment", ((Client) trackingObject).getName(),
                    GenericTools.formatTime(new Date()));
        } else if (trackingType == TrackingType.productDelete) {
            return "- " + messages.getLabel("tracking_product_delete_comment", ((Product) trackingObject).getName(),
                    GenericTools.formatTime(new Date()));
        } else if (trackingType == TrackingType.serviceDelete) {
            return "- " + messages.getLabel("tracking_service_delete_comment", ((Service) trackingObject).getName(),
                    GenericTools.formatTime(new Date()));
        } else if (trackingType == TrackingType.saleDelete) {
            Sale sale = (Sale) trackingObject;
            String message = sale.getClient() == null ?
                    messages.getLabel("tracking_sale_without_client_delete_comment", GenericTools.formatDate(sale.getDate()), GenericTools.formatTime(new Date())) :
                    messages.getLabel("tracking_sale_delete_comment", GenericTools.formatDate(sale.getDate()), sale.getClient().getName(), GenericTools.formatTime(new Date()));

            return "- " + message;

        } else if (trackingType == TrackingType.quoteDelete) {
            Sale sale = (Sale) trackingObject;
            String message = sale.getClient() == null ?
                    messages.getLabel("tracking_quote_without_client_delete_comment", GenericTools.formatDate(sale.getDate()), GenericTools.formatTime(new Date())) :
                    messages.getLabel("tracking_quote_delete_comment", GenericTools.formatDate(sale.getDate()), sale.getClient().getName(), GenericTools.formatTime(new Date()));

            return "- " + message;

        } else if (trackingType == TrackingType.expenseDelete) {
            Expense expense = (Expense) trackingObject;
            return "- " + messages.getLabel("tracking_expense_delete_comment", expense.getCategory(),
                    ServerTools.formatAmount(getSessionUser().getEnterprise().getLanguage(), expense.getPaymentValue()),
                    GenericTools.formatTime(new Date()));
        }
        return null;
    }

    public boolean isDeleteTrack(TrackingType trackingType) {
        return trackingType == TrackingType.clientDelete
                || trackingType == TrackingType.productDelete
                || trackingType == TrackingType.serviceDelete
                || trackingType == TrackingType.saleDelete
                || trackingType == TrackingType.quoteDelete
                || trackingType == TrackingType.expenseDelete;
    }
}
